﻿using System;
using Hopscotch.Common.Logging;
using Hopscotch.Server.EnqSignalRHost;
using Hopscotch.Server.EnqSignalRHost.Hubs;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.AspNet.SignalR.Infrastructure;
using Microsoft.Owin;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Microsoft.Practices.Unity;
using Newtonsoft.Json;
using Owin;

[assembly: OwinStartup(typeof(Hopscotch.Application.FakeServer.SignalRManager))]
namespace Hopscotch.Application.FakeServer
{
    public class SignalRManager : IDisposable
    {
        // Track whether Dispose has been called.
        private bool disposed = false;

        private readonly IUnityContainer container;

        public SignalRManager(IUnityContainer container)
        {
            this.container = container;
        }

        static readonly ILogger logger = AppLogger.CreateLogger<SignalRManager>();

        private IDisposable server;
        public void Start()
        {
            string url = "http://localhost:8080";

            GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new UnityHubActivator(container));
            GlobalHost.HubPipeline.AddModule(new ErrorHandlingPipelineModule());

            var jsonSerializer = GlobalHost.DependencyResolver.Resolve<JsonSerializer>();
            jsonSerializer.TypeNameHandling = TypeNameHandling.Auto;

            container.RegisterInstance<IConnectionManager>(GlobalHost.ConnectionManager);

            //For debugging only, increase the connection timeouts
            GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromMinutes(60);
            GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromMinutes(60);

            // Add this line to load Hubs (rubish)
            AppDomain.CurrentDomain.Load(typeof(DiagnosticsEnqHub).Assembly.FullName);

            server = WebApp.Start(url);

            logger.Info("SignalR Server running on {0}", url);
        }

        public void Configuration(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);
            GlobalHost.Configuration.DefaultMessageBufferSize = 100;
            var hubConfiguration = new HubConfiguration();

            hubConfiguration.EnableDetailedErrors = true;

            app.MapSignalR(hubConfiguration);
        }

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }


        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing && server != null)
                {
                    // Dispose managed resources.
                    server.Dispose();
                }
                // Call the appropriate methods to clean up
                // unmanaged resources here.

                // Note disposing has been done.
                disposed = true;
            }
        }

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~SignalRManager()
        {
            Dispose(false);
        }
    }

}
